//
//  HexMap.cpp
//  DiceWar
//
//  Created by xiaofeng on 19/6/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#include "HexMap.h"
#include "MapGraph.h"
#include "RandomGenerator.h"
#include <vector>

HexMap::HexMap() {}
HexMap::~HexMap() {}

void HexMap::init(int numPlayers)
{
    generate(numPlayers);
}

void HexMap::generate(int numPlayers)
{
    MapGraph graph;
    graph.init(&m_map);
    
    reset();
    
    const int kStartNumDices = getNumStartDicesFromNumPlayers(numPlayers);
    HexMapGeneratingStrategyNormal normalGeneratingStrategy;
    normalGeneratingStrategy.generate(numPlayers, kStartNumDices, *this);
    
    while (!graph.isGraphSinglePiece())
    {
        reset();
        normalGeneratingStrategy.generate(numPlayers, kStartNumDices, *this);
    }
}

void HexMap::reset()
{
    for (MatrixIter iter = m_map.begin(); iter != m_map.end(); ++iter)
    {
        iter->setType(HexMapGrid::kWall);
        iter->setPlayerType(kInvalidPlayer);
        iter->setNumDices(0);
    }
}

int HexMap::getNumStartDicesFromNumPlayers(int numPlayers)
{
    int numStartDeices = 0;
    switch (numPlayers) 
    {
        case 2:
            numStartDeices = 50;
            break;
            
        case 3:
            numStartDeices = 40;
            break;
        
        case 4:
            numStartDeices = 30;
            break;
            
        default:
            numStartDeices = 20;
            break;
    }

    return numStartDeices;
}

void HexMap::setMapGrid(int xIndex, int yIndex, const HexMapGrid& grid)
{
    m_map.setValue(xIndex, yIndex, grid);
}

HexMapGrid& HexMap::getMapGrid(int xIndex, int yIndex)
{
    return m_map(xIndex, yIndex);
}

cocos2d::CCPoint HexMap::getMapGridPosition(int coordinateX, int coordinateY) const
{
    const HexMapGrid& grid = getMapGrid(coordinateX, coordinateY);
    return grid.getPosition();
}

const HexMapGrid& HexMap::getMapGrid(int xIndex, int yIndex) const
{
    return m_map(xIndex, yIndex);
}

int HexMap::getNumPlayerCells(PlayerType type) const
{
    int numPlayerCells = 0;
    
    for (MatrixConstIter iter = m_map.begin(); iter != m_map.end(); ++iter)
    {
        if (iter->getPlayerType() != type) continue;
        numPlayerCells++;
    }
        
    return numPlayerCells;
}

bool HexMap::isCellOcupiedByPlayer(int xIndex, int yIndex, PlayerType type) const
{
    const HexMapGrid& grid = m_map(xIndex, yIndex);
    return grid.getPlayerType() == type;
}

void HexMap::addDicesRandomlyToPlayer(int numDicesToAdd, PlayerType type)
{
    std::vector<int> playerDices;
    
    for (MatrixConstIter iter = m_map.begin(); iter != m_map.end(); ++iter)
    {
        if (iter->getPlayerType() != type) continue;
        playerDices.push_back(iter->getNumDices());
    }
        
    RandomGenerator random;
    const int kNumCells = static_cast<int>(playerDices.size());
    random.getRandomSegmentsWithPreAllocation(numDicesToAdd, kNumCells, 1, gameConstants::kMaxNumDicesPerGrid, playerDices);
    
    int vecIndex = 0;
    for (MatrixIter iter = m_map.begin(); iter != m_map.end(); ++iter)
    {
        if (iter->getPlayerType() != type) continue;
        iter->setNumDices(playerDices[vecIndex++]);
    }
}

HexCellCoordinate HexMap::getMapGridCoordinate(const cocos2d::CCPoint& point) const
{
    HexCellCoordinate coordinate(-1, -1);
    const float distanceSquareThreshold = gameConstants::kHexGridSize * gameConstants::kHexGridSize;
    
    for (HexMapGridMatrix::const_iterator iter = m_map.begin(); iter != m_map.end(); ++iter)
    {
        cocos2d::CCPoint gridPosition = iter->getPosition();
        float distanceSquare = mathUtil::getDistanceSquare(gridPosition, point);
        if (distanceSquare >= distanceSquareThreshold) continue;
        
        return iter->getCoordinate(); 
    }
  
    return coordinate;
}